package com.michaelbulava.TFS.vcs.internal;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.UpdateSession;
import com.intellij.vcsUtil.VcsUtil;
import com.michaelbulava.TFS.Messages;
import com.michaelbulava.TFS.log.FileLogger;
import com.michaelbulava.TFS.vc.tfsitem.TFSFile;
import com.michaelbulava.TFS.vcs.TFSVcs;
import com.michaelbulava.TFS.vcs.exceptions.TFSException;
import com.michaelbulava.TFS.vcs.utils.TFSFileUtil;
import com.michaelbulava.TFS.vcs.utils.TFSProgressUtil;
import com.michaelbulava.TFS.vcs.utils.TFSUtil;
import com.microsoft.tfs.core.clients.versioncontrol.GetOptions;
import com.microsoft.tfs.core.clients.versioncontrol.GetStatus;
import com.microsoft.tfs.core.clients.versioncontrol.PendChangesOptions;
import com.microsoft.tfs.core.clients.versioncontrol.events.*;
import com.microsoft.tfs.core.clients.versioncontrol.path.ItemPath;
import com.microsoft.tfs.core.clients.versioncontrol.path.LocalPath;
import com.microsoft.tfs.core.clients.versioncontrol.path.ServerPath;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.*;
import com.microsoft.tfs.core.clients.versioncontrol.specs.ItemSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.VersionSpec;
import com.microsoft.tfs.core.util.FileEncoding;
import com.microsoft.tfs.util.StringUtil;
import com.microsoft.tfs.util.tasks.TaskMonitor;
import com.microsoft.tfs.util.tasks.TaskMonitorService;
import javafx.scene.control.TableView;
import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.ant.FileIterator;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Created by MichaelA on 8/5/2015.
 */
public class SharedOperations {
    //TODO replace hardcoded strings with String resources
    private static final Logger log = FileLogger.getInstance(SharedOperations.class);

    public static Collection<VcsException> scheduleForAddition(final Project project, Workspace workspace, List<FilePath> files){
        final List<FilePath> addedFiles = new ArrayList<>();

        standardNonFatalErrorListener errorListener = new standardNonFatalErrorListener();

        NewPendingChangeListener addedListener = new NewPendingChangeListener() {
            @Override
            public void onNewPendingChange(PendingChangeEvent event) {
                if (event.getPendingChange().getChangeType().containsAny(ChangeType.ADD)){
                    FilePath file = TFSFileUtil.getFilePath(event.getPendingChange().getLocalItem(),
                            event.getPendingChange().getItemType() == ItemType.FOLDER);
                    addedFiles.add(file);
                }
            }
        };

        try{
            List<String> myFiles = new ArrayList<String>();
            for(FilePath file : files){
                if(!TFSVcs.getInstance(project).isIgnoredFile(file))
                    myFiles.add(file.getPath());
            }


            workspace.getClient().getEventEngine().addNonFatalErrorListener(errorListener);
            workspace.getClient().getEventEngine().addNewPendingChangeListener(addedListener);

            int count = workspace.pendAdd(myFiles.toArray(new String[myFiles.size()]), false,
                    FileEncoding.AUTOMATICALLY_DETECT, LockLevel.NONE, GetOptions.GET_ALL,
                    PendChangesOptions.NONE);

            TFSFileUtil.markFilesDirty(project, addedFiles);

            return TFSUtil.getVcsExceptions(errorListener.getFailures());
        } finally {
            workspace.getClient().getEventEngine().removeNonFatalErrorListener(errorListener);
            workspace.getClient().getEventEngine().removeNewPendingChangeListener(addedListener);

        }
    }

    public static Collection<VcsException> performUndo(final Project project, Workspace workspace, List<FilePath> files,
                                                       ProgressIndicator indicator){
        Collection<VcsException> errors = new ArrayList<VcsException>();
        if (files.size() > 0){
            standardNonFatalErrorListener errorListener = new standardNonFatalErrorListener();
            try{
                workspace.getClient().getEventEngine().addNonFatalErrorListener(errorListener);

                ItemSpec[] items = TFSFileUtil.getItemSpecs(project, workspace, files);
                if (indicator != null)
                    TaskMonitorService.pushTaskMonitor(new MyTaskMonitor(indicator));

                workspace.undo(items, GetOptions.GET_ALL, true, (String[])null);
            } finally {
                workspace.getClient().getEventEngine().removeNonFatalErrorListener(errorListener);

                TFSFileUtil.refreshAndInvalidate(project, files.toArray(new FilePath[0]), true);
            }
            errors.addAll(TFSUtil.getVcsExceptions(errorListener.getFailures()));
        }
        return errors;
    }

    public static Collection<VcsException> scheduleForDeletion(final Project project, Workspace workspace,
                                                               List<FilePath> files, ProgressIndicator indicator){
        Collection<VcsException> errors = new ArrayList<>();
        standardGetListener getListener = new standardGetListener();
        standardNonFatalErrorListener nonFatalErrorListener = new standardNonFatalErrorListener();
        try{
            ItemSpec[] itemSpecs = TFSFileUtil.getItemSpecs(project, workspace, files);
            PendingSet pendingSet =workspace.getPendingChanges(itemSpecs, false);
            PendingChange[] pendingChanges = pendingSet.getPendingChanges();

            List<FilePath> revert = new ArrayList<>();


            for(int i = 0; i < pendingChanges.length; i++){
                ChangeType change = pendingChanges[i].getChangeType();
                if (!change.contains(ChangeType.DELETE)) {
                    FilePath localItem = TFSFileUtil.getFilePath(pendingChanges[i].getLocalItem(),
                            pendingChanges[i].getItemType() == ItemType.FOLDER);
                    revert.add(localItem);
                }
            }
            errors.addAll(performUndo(project, workspace, revert, indicator));

            List<FilePath> undoneFiles = new ArrayList<>(files.size());
            for(FilePath originalFile : files){
                if(revert.contains(originalFile))
                    undoneFiles.add(originalFile);
            }

            final List<FilePath> scheduleForDeletion = new ArrayList<>();

            StatusProvider.visitByStatus(workspace, undoneFiles, false, null,
                    new StatusVisitor() {
                        @Override
                        protected void performNotVersion(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performDeleted(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performScheduledForAddition(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performScheduledForDeletion(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performCheckedOutForEdit(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performOutOfDate(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
                            scheduleForDeletion.add(filePath);
                        }

                        @Override
                        protected void performUpToDate(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
                            scheduleForDeletion.add(filePath);
                        }

                        @Override
                        protected void performRenamed(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performRenamedCheckedOut(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performUndeleted(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }

                        @Override
                        protected void performIgnored(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

                        }
                    }, project);

            itemSpecs = TFSFileUtil.getItemSpecs(project, workspace, scheduleForDeletion);

            workspace.getClient().getEventEngine().addGetListener(getListener);
            workspace.getClient().getEventEngine().addNonFatalErrorListener(nonFatalErrorListener);
            workspace.pendDelete(itemSpecs, LockLevel.UNCHANGED, GetOptions.GET_ALL,
                    PendChangesOptions.FORCE_CHECK_OUT_LOCAL_VERSION);

            errors.addAll(TFSUtil.getVcsExceptions(nonFatalErrorListener.getFailures()));

            TFSFileUtil.markFilesDirty(project, getListener.getResults());

        } catch(Throwable tr){
            errors.add(new VcsException(tr));
        } finally {
            workspace.getClient().getEventEngine().removeNonFatalErrorListener(nonFatalErrorListener);
            workspace.getClient().getEventEngine().removeGetListener(getListener);
        }
        return errors;
    }

    public static Collection<VcsException> scheduleRename(Project project, Workspace workspace,
                                                          List<FilePath> workspaceFiles, Map<FilePath, FilePath> renameMap){
        standardNonFatalErrorListener errorListener = new standardNonFatalErrorListener();
        standardGetListener getListener = new standardGetListener();
        Collection<VcsException> errors = new ArrayList<>();
        try {
            StatusProvider.visitByStatus(workspace, workspaceFiles, false, null,
                    new PerformMoveStatusVisitor(renameMap), project);


            workspace.getClient().getEventEngine().addGetListener(getListener);
            workspace.getClient().getEventEngine().addNonFatalErrorListener(errorListener);

            workspace.pendRename(TFSFileUtil.getFilePathStrings(renameMap.keySet()),
                    TFSFileUtil.getFilePathStrings(renameMap.values()),
                    LockLevel.UNCHANGED, GetOptions.GET_ALL, true, PendChangesOptions.GET_LATEST_ON_CHECKOUT);

            errors.addAll(TFSUtil.getVcsExceptions(errorListener.getFailures()));

            TFSFileUtil.markDirtyRecursively(project, getListener.getResults());
        } finally {
            workspace.getClient().getEventEngine().removeGetListener(getListener);
            workspace.getClient().getEventEngine().removeNonFatalErrorListener(errorListener);

            TFSFileUtil.refreshAndInvalidate(project, renameMap.values().toArray(new FilePath[0]), true);
            TFSFileUtil.refreshAndInvalidate(project, renameMap.keySet().toArray(new FilePath[0]), true);
        }
        return errors;
    }

    public static Collection<VcsException> performCheckin(Project project, Workspace workspace,
                                                          List<FilePath> checkinFiles, String checkinComment,
                                                          CheckinNote checkinNote,
                                                          WorkItemCheckinInfo[] workItemCheckinInfos,
                                                          PolicyOverrideInfo policyOverrideInfo){
        Collection<VcsException> errors = new ArrayList<>();

        standardNonFatalErrorListener errorListener = new standardNonFatalErrorListener();
        standardCheckinListener checkinListener = new standardCheckinListener(null, errors);


        try {
            ItemSpec[] itemSpecs = TFSFileUtil.getItemSpecs(project, workspace, checkinFiles);
            PendingChange[] pendingChanges = workspace.getPendingChanges(itemSpecs, false).getPendingChanges();

            Map<FilePath, PendingChange> pendingChangeMap = new HashMap<>();
            for (int i = 0; i < pendingChanges.length; i++) {
                FilePath pendingFile = TFSFileUtil.getFilePath(pendingChanges[i].getLocalItem(),
                        pendingChanges[i].getItemType() == ItemType.FOLDER);
                pendingChangeMap.put(pendingFile, pendingChanges[i]);
            }

            List<PendingChange> checkinChanges = new ArrayList<>();
            boolean allFilesFound = true;
            for (FilePath file : checkinFiles) {
                PendingChange pendingChange = pendingChangeMap.get(file);
                if (pendingChange == null) {
                    errors.add(new VcsException(MessageFormat.format(Messages.getString("SharedOperations.CheckinPendingChangeNotFoundForFileFormat"),
                            new Object[]{file.getPath()})));
                    allFilesFound = false;
                } else {

                    checkinChanges.add(pendingChange);
                }
            }
            //If we can't locate every file passed to us we need to stop.
            if (!allFilesFound)
                return errors;
            workspace.getClient().getEventEngine().addNonFatalErrorListener(errorListener);
            workspace.getClient().getEventEngine().addCheckinListener(checkinListener);

            int fileCount = workspace.checkIn(checkinChanges.toArray(new PendingChange[checkinChanges.size()]),
                    checkinComment, checkinNote, workItemCheckinInfos, policyOverrideInfo);
            log.warn(String.format("%d files have been checked in.", fileCount));

            errors.addAll(TFSUtil.getVcsExceptions(errorListener.getFailures()));
            TFSFileUtil.markFilesDirty(project, checkinListener.getCommittedFiles());
        }catch(Throwable tr){
            errors.add(new VcsException(tr));
        } finally {
            workspace.getClient().getEventEngine().removeNonFatalErrorListener(errorListener);
            workspace.getClient().getEventEngine().removeCheckinListener(checkinListener);

            TFSFileUtil.refreshAndInvalidate(project, checkinFiles.toArray(new FilePath[0]), true);
        }
        return errors;
    }


    public static Collection<VcsException> performGet(Project project, Workspace workspace,
                                                      ProgressIndicator indicator, List<FilePath> getFiles,
                                                      VersionSpec versionSpec, boolean recursive){
        Collection<VcsException> errors = new ArrayList<>();
        standardGetListener getListener = new standardGetListener(indicator);
        standardNonFatalErrorListener errorListener = new standardNonFatalErrorListener();

        try{
            GetRequest[] requests = TFSFileUtil.getGetRequests(project, workspace, getFiles, versionSpec, recursive);
            AtomicReference<Conflict[]> conflicts = new AtomicReference<Conflict[]>();

            workspace.getClient().getEventEngine().addGetListener(getListener);
            workspace.getClient().getEventEngine().addNonFatalErrorListener(errorListener);

            TaskMonitorService.pushTaskMonitor(new MyTaskMonitor(indicator));

            GetStatus status = workspace.get(requests, GetOptions.NONE);

            //Make sure we really were successful
            if (TFSProgressUtil.isCancelled(indicator))
                errors.add(new VcsException("Operation has been cancelled", true));
            if (!errorListener.getFailures().isEmpty())
                errors.addAll(TFSUtil.getVcsExceptions(errorListener.getFailures()));
            if (status.getNumOperations() != status.getNumUpdated())
                errors.add(new VcsException("Does not appear that all items were downloaded from Team Foundation server that were requested...", false));

            if (status.getNumOperations() == 0)
                errors.add(new VcsException("Nothing to download from Team Foundation Server.", true));
            //status.
        } catch(Throwable tr){
            errors.add(new VcsException(tr));
        } finally{
            workspace.getClient().getEventEngine().removeGetListener(getListener);
            workspace.getClient().getEventEngine().removeNonFatalErrorListener(errorListener);

            TFSFileUtil.refreshAndInvalidate(project, getFiles.toArray(new FilePath[0]), true);
        }

        return errors;
    }

    public static Collection<VcsException> performCheckout(Project project, Workspace workspace, List<FilePath> checkoutFiles){
        final Collection<VcsException> errors = new ArrayList();

        log.info(String.format("Executing SharedOperations.performCheckout of %1$d files in %2$s workspace.",
                checkoutFiles.size(), workspace.getName()));

        standardNonFatalErrorListener errorListener = new standardNonFatalErrorListener();
        standardPendingOperationCompletedLisener completedListener = new standardPendingOperationCompletedLisener();
        standardGetListener getListener = new standardGetListener();
        //standardPendingOperationCompletedLisener completedListener = new standardPendingOperationCompletedLisener();

        //TODO read LockLevel,Update on CheckOut from settings
        try{
            ItemSpec[] itemSpecs = TFSFileUtil.getItemSpecs(project, workspace, checkoutFiles);

            workspace.getClient().getEventEngine().addNonFatalErrorListener(errorListener);
            workspace.getClient().getEventEngine().addOperationCompletedListener(completedListener);
            workspace.getClient().getEventEngine().addGetListener(getListener);

            int result = workspace.pendEdit(itemSpecs, LockLevel.UNCHANGED, FileEncoding.AUTOMATICALLY_DETECT,
                    GetOptions.NONE, PendChangesOptions.FORCE_CHECK_OUT_LOCAL_VERSION);
            log.warn(String.format("%d file(s) checked out for editing", result));
//            try{
//                TFSFileUtil.setReadonly(completedListener.getChangedFiles(), false);
//            } catch (IOException e) {
//                errors.add(new VcsException(e));
//            }
            errors.addAll(TFSUtil.getVcsExceptions(errorListener.getFailures()));
        } catch (Throwable tr){
            errors.add(new VcsException(tr));
        } finally{
            workspace.getClient().getEventEngine().removeNonFatalErrorListener(errorListener);
            workspace.getClient().getEventEngine().removeOperationCompletedListener(completedListener);
            workspace.getClient().getEventEngine().removeGetListener(getListener);

            //Refresh the file status
            TFSFileUtil.refreshAndInvalidate(project, checkoutFiles.toArray(new FilePath[0]), true);
        }
        return errors;
    }



    private static class standardNonFatalErrorListener implements NonFatalErrorListener{
        private List<Failure> failures = new ArrayList<Failure>();
        private List<Throwable> exceptions = new ArrayList<Throwable>();

        @Override
        public void onNonFatalError(NonFatalErrorEvent event) {
            if (event.getFailure() != null)
                failures.add(event.getFailure());
            if (event.getThrowable() != null)
                exceptions.add(event.getThrowable());

            log.warn("Captured NonFatalError: " + event.getFailure().getFormattedMessage(), event.getThrowable());
        }

        public final List<Failure> getFailures(){
            return failures;
        }

        public final List<Throwable> getThrowable(){
            return this.exceptions;
        }
    }

    private static class standardUndoOperationCompletedEvent implements OperationCompletedListener{

        @Override
        public void onOperationCompleted(OperationCompletedEvent event) {
            if (event  instanceof UndoOperationCompletedEvent){
                UndoOperationCompletedEvent undoEvent = (UndoOperationCompletedEvent)event;


            }
        }
    }

    private static class standardGetListener implements GetListener{
        private List<FilePath> getResults = new ArrayList<>();

        private final ProgressIndicator indicator;

        public standardGetListener(){
            this(null);
        }

        public standardGetListener(ProgressIndicator indicator){
            this.indicator = indicator;
        }

        @Override
        public void onGet(GetEvent event) {
            if (StringUtils.isNotEmpty(event.getTargetLocalItem()))
//                TFSProgressUtil.setProgressText2(indicator, MessageFormat.format(
//                        Messages.getString("SharedOperations.standardGetListener.GotTextFormat"),
//                        new Object[]{ event.getTargetLocalItem() }));

            getResults.add(TFSFileUtil.getFilePath(event.getTargetLocalItem(), event.getItemType() == ItemType.FOLDER));
        }

        public List<FilePath> getResults(){
            return this.getResults;
        }
    }

    private static class standardCheckinListener implements CheckinListener{
        private int changeSet;
        private List<FilePath> committedFiles = new ArrayList<>();
        private final ProgressIndicator progressIndicator;
        private final Collection<VcsException> errors;

        public standardCheckinListener(){
            this(null, null);
        }

        public standardCheckinListener(ProgressIndicator indicator, Collection<VcsException> errors){
            this.progressIndicator = indicator;
            this.errors = errors;
        }

        @Override
        public void onCheckin(CheckinEvent checkinEvent) {
            this.changeSet = checkinEvent.getChangesetID();
            TFSProgressUtil.setProgressText2(progressIndicator, "Reading Checked in files...");
            PendingChange[] pendingChanges = checkinEvent.getCommittedChanges();
            for(int i = 0; i < pendingChanges.length; i++){
                committedFiles.add(TFSFileUtil.getFilePath(pendingChanges[i].getLocalItem(),
                        pendingChanges[i].getItemType() == ItemType.FOLDER));
            }
            //Check-in operation should manage setting file readonly, based on workspace type
        }

        public final int getChangeSetId(){
            return this.changeSet;
        }

        public List<FilePath> getCommittedFiles(){
            return this.committedFiles;
        }
    }


    private static class standardPendingChangeListener implements PendingChangesChangedListener{

        @Override
        public void onPendingChangesChanged(WorkspaceEvent workspaceEvent) {

        }
    }

    private static class standardPendingOperationCompletedLisener implements OperationCompletedListener{
        private ChangeRequest[] requests;
        private Workspace workspace;
        @Override
        public void onOperationCompleted(OperationCompletedEvent event) {
            if (event  instanceof PendOperationCompletedEvent){
                PendOperationCompletedEvent pocEvent = (PendOperationCompletedEvent)event;
                requests = pocEvent.getRequests();
                workspace = pocEvent.getWorkspace();
            }
        }

        public ChangeRequest[] getChangeRequests(){
            return requests;
        }

        public List<FilePath> getChangedFiles(){
            List<FilePath> files = new ArrayList<>();
            for(int i = 0; i < requests.length; i++){
                if (!ServerPath.isServerPath(requests[i].getItemSpec().getItem()))
                    files.add(TFSFileUtil.getFilePath(requests[i].getTargetItem(),
                            requests[i].getItemType() == ItemType.FOLDER));
                else {
                    for(WorkingFolder folder : workspace.getFolders()){
                        if (ServerPath.isChild(folder.getServerItem(), requests[i].getItemSpec().getItem())){
                            String localPath = ServerPath.makeLocal(requests[i].getItemSpec().getItem(),
                                    folder.getServerItem(), folder.getLocalItemRaw());
                            files.add(TFSFileUtil.getFilePath(localPath, requests[i].getItemType() == ItemType.FOLDER));
                        }
                    }
                }

            }
            return files;
        }
    }

    private static class PerformMoveStatusVisitor extends StatusVisitor {
        final Map<FilePath, FilePath> scheduleMove = new HashMap<FilePath, FilePath>();
        final Map<FilePath, FilePath> movedPaths;

        public PerformMoveStatusVisitor(Map<FilePath, FilePath> movedPaths){
            this.movedPaths= movedPaths;
        }
//        public void setMovedPaths(Map<FilePath, FilePath> movedPaths){
//            this.movedPaths = movedPaths;
//        }
//
//        public void clear(){
//            scheduleMove.clear();
//        }

        public Map<FilePath, FilePath> getScheduleMove(){
            return scheduleMove;
        }


        @Override
        protected void performNotVersion(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

        }

        @Override
        protected void performDeleted(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

        }

        @Override
        protected void performScheduledForAddition(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performScheduledForDeletion(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performCheckedOutForEdit(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performOutOfDate(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performUpToDate(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performRenamed(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performRenamedCheckedOut(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performUndeleted(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {
            scheduleMove.put(filePath, movedPaths.get(filePath));
        }

        @Override
        protected void performIgnored(FilePath filePath, boolean existsLocally, ServerStatus serverStatus) {

        }
    };


    public static class MyTaskMonitor implements TaskMonitor{
        private final ProgressIndicator indicator;
        private final TaskMonitor parentMonitor;
        private int _totalWork;

        public MyTaskMonitor(ProgressIndicator indicator){
            this.indicator = indicator;
            this.parentMonitor = null;
        }


        @Override
        public void begin(String taskName, int totalWork) {
            try {
                TFSProgressUtil.setIndeterminate(indicator, totalWork <= 0);
                TFSProgressUtil.setProgressText(indicator, taskName);
                this._totalWork = totalWork;
            } catch(Throwable tr){
                tr.printStackTrace();
            }
        }

        @Override
        public void beginWithUnknownTotalWork(String taskName) {
            begin(taskName, -1);
        }

        @Override
        public void done() {
            //TFSProgressUtil.stop(indicator);
        }

        @Override
        public boolean isCanceled() {
            try{
                return TFSProgressUtil.isCancelled(indicator);
            } catch(Throwable tr){
                tr.printStackTrace();
                return false;
            }
        }

        @Override
        public void setCanceled() {
            try{
                TFSProgressUtil.setCancelled(indicator);
            } catch(Throwable tr){
                tr.printStackTrace();
            }
        }

        @Override
        public void worked(int amount) {
            try{
                TFSProgressUtil.updateWorkedFraction(indicator, amount, _totalWork);
            } catch(Throwable tr){
                tr.printStackTrace();
            }
        }

        @Override
        public void setTaskName(String taskName) {
            try{
                TFSProgressUtil.setProgressText(indicator, taskName);
            } catch(Throwable tr){
                tr.printStackTrace();
            }
        }

        @Override
        public void setCurrentWorkDescription(String description) {
            try{
                TFSProgressUtil.setProgressText2(indicator, description);
            } catch(Throwable tr){
                tr.printStackTrace();
            }
        }

        @Override
        public TaskMonitor newSubTaskMonitor(int amount) {
            try {
                return new MyTaskMonitor(this.indicator);
            } catch (Throwable tr){
                tr.printStackTrace();
                return null;
            }
        }
    }


    public static class TFSUpdateSession implements UpdateSession{

        @NotNull
        @Override
        public List<VcsException> getExceptions() {
            return null;
        }

        @Override
        public void onRefreshFilesCompleted() {

        }

        @Override
        public boolean isCanceled() {
            return false;
        }
    }
}
